#include "ulib.h"

struct file_process_t
{
	 mutex_t lock;
	 struct fs_node_t *nodes;
	 struct fs_node_t *free_head;
};

// universal wrapper for drivers {{{
static int
fs_map(struct fs_node_t *f, faddr_t start, int size, void *addr)
{
	 if (f->drv->map == NULL) return -E_UNSUPPORTED;
	 return f->drv->map(f, start, size, addr);
}

static int
fs_update(struct fs_node_t *f, faddr_t start, int size, void *addr)
{
	 if (f->drv->update == NULL) return -E_UNSUPPORTED;
	 return f->drv->update(f, start, size, addr);
}

static int
fs_open(struct fs_node_t *d, const fchar_t *name, struct fs_node_t *f)
{
	 if (f->drv->open == NULL) return -E_UNSUPPORTED;
	 return f->drv->open(d, name, f);
}

static int
fs_stat(struct fs_node_t *f, struct fs_stat_t *attr)
{
	 if (f->drv->stat == NULL) return -E_UNSUPPORTED;
	 return f->drv->stat(f, attr);
}

static int
fs_move(struct fs_node_t *f, struct fs_node_t *d, const fchar_t *name)
{
	 if (f->drv->move == NULL) return -E_UNSUPPORTED;
	 return f->drv->move(f, d, name);
}

static int
fs_close(struct fs_node_t *f)
{
	 if (f->drv->close == NULL) return -E_UNSUPPORTED;
	 return f->drv->close(f);
}
// }}}

/* RAMFS Implementation ======================================= */


/* IPC Interface ============================================== */

#define FILE_NODE_COUNT 8192

struct ipc_node_t file_ipc;
extern const char ramfs_image[];

static void
file_process(void *_data)
{
	 struct file_process_t fp;
	 fp.nodes  = (struct fs_node_t *)bmalloc(sizeof(struct fs_node_t) * FILE_NODE_COUNT);
	 fp.free_head = fp.nodes;
	 int i;
	 for (i = 1; i != FILE_NODE_COUNT; ++ i)
	 {
		  fp.nodes[i].next = fp.nodes + i + 1;
	 }
	 fp.nodes[FILE_NODE_COUNT - 1].next = NULL;

	 struct fs_node_t *root = fp.nodes;
	 fp.free_head = fp.nodes + 1;

	 ramfs_import(ramfs_image, root);
	 
	 while (1)
	 {
		  ipc_accept(&file_ipc);
		  ipc_ser_trans_wait(&file_ipc);

		  uint32_t method = *(uint32_t *)(file_ipc.calls);
	 	  uint32_t result = 0;

		  switch (method)
		  {
		  case FILE_OPEN_ROOT:
		  {
			   break;
		  }
		  case FILE_OPEN:
		  {
			   break;
		  }
		  case FILE_INFO:
		  {
			   break;
		  }
		  case FILE_MAP_IO:
		  {
			   break;
		  }
		  case FILE_CLOSE:
		  {
			   break;
		  }
		  }

		  *(uint32_t *)(file_ipc.rets) = result;		  
		  ipc_ser_trans_yield(&file_ipc);
		  ipc_ser_trans_wait(&file_ipc);
	 }
}

void
file_start(void)
{
	 ipc_node_init(&file_ipc);
	 process_create(file_process, NULL, 8192);
}	 

file_t file_open_root()
{
	 ipc_connect(&file_ipc);

	 *(uint32_t *)(file_ipc.calls) = FILE_OPEN_ROOT;
	 ipc_cli_trans_yield(&file_ipc);
	 ipc_cli_trans_wait(&file_ipc);
	 int result = *(uint32_t *)(file_ipc.rets);
	 ipc_cli_trans_yield(&file_ipc);

	 return result;	 
}

file_t
file_open(file_t base, const fchar_t *name)
{
	 
}

void 
file_info(file_t file, struct file_info_t *info)
{
}

physaddr_t
file_map_io(file_t file, int offset)
{
}

void file_close(file_t file)
{
}
